package cn.itcast.nems.manager.msas;

import com.itcast.msas.sdk.acm.api.AccountApi;
import com.itcast.msas.sdk.acm.api.AcmMetadataApi;
import com.itcast.msas.sdk.acm.domain.AccountDto;
import com.itcast.msas.sdk.acm.domain.AccountResourceDto;
import com.itcast.msas.sdk.acm.domain.Role;
import com.itcast.msas.sdk.base.OpenApiFactory;
import com.itcast.msas.sdk.base.auth.MsasAuth;
import com.itcast.msas.sdk.base.support.MsasApiResponse;
import com.itcast.msas.sdk.msg.api.WechatMsgApi;
import com.itcast.msas.sdk.msg.domain.WechatTxtMsgDto;
import com.itcast.msas.sdk.usr.api.MsasUserApi;
import com.itcast.msas.sdk.usr.domain.MsasUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * author: yong.li
 * create: 2023-08-15 13:53:19
 **/
public class MsasManager {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final AccountApi accountApi;
    private final AcmMetadataApi acmMetadataApi;

    private final MsasUserApi msasUserApi;
    private final WechatMsgApi wechatMsgApi;

    public MsasManager(String clientId, String clientKey, String baseUrl) {
        logger.info("Msas init with clientId:{}, baseUrl:{}", clientId, baseUrl);
        new MsasAuth
                .MsasAuthBuilder()
                .setClientId(clientId)
                .setPrivateKey(clientKey)
                .setBaseUrl(baseUrl)
                .build();
        this.accountApi = OpenApiFactory.getOpenApi(AccountApi.class);
        this.acmMetadataApi = OpenApiFactory.getOpenApi(AcmMetadataApi.class);
        this.msasUserApi = OpenApiFactory.getOpenApi(MsasUserApi.class);
        this.wechatMsgApi = OpenApiFactory.getOpenApi(WechatMsgApi.class);
    }

    /**
     * 给员工发企业微信消息
     *
     * @param email   公司邮箱
     * @param message 消息内容
     */
    public void sendWechatMessage(String email, String message) {
        WechatTxtMsgDto dto = new WechatTxtMsgDto();
        dto.setAccounts(List.of(email));
        dto.setContent(message);
        final MsasApiResponse<?> response = this.wechatMsgApi.sendTextMsg(dto);
        if (response.getCode().equals(MsasApiResponse.OK)) {
            return;
        }
        logger.warn("code: {} message: {}", response.getCode(), response.getMessage());
        throw new RuntimeException("给'" + email + "'发企业微信消息'" + message + "'失败," + response.getMessage());
    }

    /**
     * 获取账号信息
     *
     * @param account 员工邮箱
     * @return 账号信息
     */
    public AccountDto getAccount(String account) {
        if (account == null || account.trim().isEmpty()) {
            throw new RuntimeException("account参数不能为空");
        }
        final MsasApiResponse<AccountDto> response = this.accountApi.getAccount(account);
        if (response.getCode().equals(MsasApiResponse.OK)) {
            return response.getResult();
        }
        logger.warn("code: {} message: {}", response.getCode(), response.getMessage());
        throw new RuntimeException("获取" + account + "账号失败," + response.getMessage());
    }

    /**
     * 获取用户的角色代码
     *
     * @param account 员工邮箱
     * @return 角色代码列表
     */
    public Set<String> getRoles(String account) {
        if (account == null || account.trim().isEmpty()) {
            throw new RuntimeException("account参数不能为空");
        }
        final MsasApiResponse<List<Role>> response = acmMetadataApi.getUserRolesMetadata(account);
        if (response.getCode().equals(MsasApiResponse.OK)) {
            final List<Role> roles = response.getResult();
            if (roles == null || roles.isEmpty()) {
                return Collections.emptySet();
            }
            return roles
                    .stream()
                    .map(Role::getCode)
                    .collect(Collectors.toSet());
        }
        logger.warn("code: {} message: {}", response.getCode(), response.getMessage());
        throw new RuntimeException("获取" + account + "角色失败," + response.getMessage());
    }

    /**
     * 获取用户权限code
     *
     * @param account 员工邮箱
     * @return 权限代码列表
     */
    public Set<String> getPermissions(String account) {
        if (account == null || account.trim().isEmpty()) {
            throw new RuntimeException("account参数不能为空");
        }
        final MsasApiResponse<AccountResourceDto> response = acmMetadataApi.getAccountMetadata(account);
        if (response.getCode().equals(MsasApiResponse.OK)) {
            final AccountResourceDto result = response.getResult();
            if (result == null) {
                return Collections.emptySet();
            }
            final List<String> resCodes = result.getResCodes();
            if (resCodes == null || resCodes.isEmpty()) {
                return Collections.emptySet();
            }
            return new HashSet<>(resCodes);
        }
        logger.warn("code: {} message: {}", response.getCode(), response.getMessage());
        throw new RuntimeException("获取" + account + "权限失败," + response.getMessage());
    }

    public MsasUser findEmployee(String employeeAccount) {
        var employeeResponse = msasUserApi.userByAccount(employeeAccount);
        Assert.isTrue(MsasApiResponse.OK.equals(employeeResponse.getCode()), "获取员工信息失败:" + employeeResponse.getMessage());
        return employeeResponse.getResult();
    }

    public List<MsasUser> findEmployees(Set<String> employeeAccountSet) {
        var result = new ArrayList<MsasUser>();
        for (String account : employeeAccountSet) {
            var employeeResponse = msasUserApi.userByAccount(account);
            Assert.isTrue(MsasApiResponse.OK.equals(employeeResponse.getCode()), "获取员工信息失败:" + employeeResponse.getMessage());
            var employee = employeeResponse.getResult();
            if (employee != null) {
                result.add(employee);
            }
        }
        return result;
    }

    public AccountResourceDto findAccountMetadata(String employeeAccount) {
        var accountMetadataResponse = acmMetadataApi.getAccountMetadata(employeeAccount);
        Assert.isTrue(MsasApiResponse.OK.equals(accountMetadataResponse.getCode()), "获取员工权限失败:" + accountMetadataResponse.getMessage());
        return accountMetadataResponse.getResult();
    }

    public List<AccountResourceDto> findAccountMetadata(Set<String> employeeAccountSet) {
        var result = new ArrayList<AccountResourceDto>();
        for (String account : employeeAccountSet) {
            var accountMetadataResponse = acmMetadataApi.getAccountMetadata(account);
            Assert.isTrue(MsasApiResponse.OK.equals(accountMetadataResponse.getCode()), "获取员工权限失败:" + accountMetadataResponse.getMessage());
            var accountMetadata = accountMetadataResponse.getResult();
            result.add(accountMetadata);
        }
        return result;
    }

    public List<Role> findRolesMetadata() {
        var rolesMetadataResponse = acmMetadataApi.getRolesMetadata();
        Assert.isTrue(MsasApiResponse.OK.equals(rolesMetadataResponse.getCode()), "获取角色信息失败:" + rolesMetadataResponse.getMessage());
        return rolesMetadataResponse.getResult();
    }

}
